﻿using System;
using System.Configuration;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Luna.Extender;
using System.Xml;

namespace Luna.Framework.Extender
{
	public class XmlExtensionManager: IExtensionManager
	{
		private IDictionary<string, Func<XmlExtensionManager, XmlNode, IExtensionItem>> creators;
		private IList<IExtensionPoint> extentions;

		public XmlExtensionManager(XmlNode node) {
			if (node == null)
				throw new ArgumentNullException("node");
			populateExtentions(node);
		}

		private void populateExtentions(XmlNode node) {
			extentions = new List<IExtensionPoint>();
			creators = new Dictionary<string, Func<XmlExtensionManager, XmlNode, IExtensionItem>>();

			registerExtentionTypes();

			foreach (XmlNode child in node.ChildNodes)
				if (child.Name.Equals("extension"))
					extentions.Add(new XmlExtensionPoint(this, child));
		}

		protected virtual void registerExtentionTypes() {
			registerExtentionType("form", (m, n) => new XmlFormExtentionItem(m, n));
			registerExtentionType("service", (m, n) => new XmlServiceExtensionItem(m, n));
		}

		public XmlExtensionManager(string filename) {
			XmlDocument doc = new XmlDocument();
			doc.Load(filename);
			XmlNode node = doc.SelectSingleNode("/extensions");
			if (node != null)
				populateExtentions(node);
			else
				throw new ApplicationException(string.Format("Extentions file corupted"));
				
		}

		public void registerExtentionType(string name, Func<XmlExtensionManager, XmlNode, IExtensionItem> creator) {
			creators[name] = creator;
		}

		internal IExtensionItem createExtentionItem(System.Xml.XmlNode child) {
			return creators.ContainsKey(child.Name) ? creators[child.Name](this, child) : new XmlExtensionItem(this, child);
		}

		#region IExtensionManager Members

		public IEnumerable<IExtensionPoint> getExtensions(string extPoint) {
			return from ep in extentions
				   where ep.Point.Equals(extPoint)
				   select ep;
		}

		public IEnumerable<IExtensionItem> getExtensionItems(string extPoint) {
			foreach (IExtensionPoint ep in getExtensions(extPoint))
				foreach (IExtensionItem item in ep.Items)
					yield return item;
		}

		public IList<IExtensionPoint> Extentions {
			get { return extentions; }
		}

		#endregion
	}
}
